#include "tasks.h"
#include <stdlib.h>     /* srand, rand */

using namespace std;

void TaskCPU(int pid, vector<int> params) { // params: n
	uso_CPU(pid, params[0]); // Uso el CPU n milisegundos.
}

void TaskIO(int pid, vector<int> params) { // params: ms_pid, ms_io,
	uso_CPU(pid, params[0]); // Uso el CPU ms_pid milisegundos.
	uso_IO(pid, params[1]); // Uso IO ms_io milisegundos.
}

void TaskAlterno(int pid, vector<int> params) { // params: ms_pid, ms_io, ms_pid, ...
	for(int i = 0; i < (int)params.size(); i++) {
		if (i % 2 == 0) uso_CPU(pid, params[i]);
		else uso_IO(pid, params[i]);
	}
}

/**
	@Ejercicio 1
    @Purpose: Simula una tarea interactiva. La tarea realiza n llamadas bloqueantes, cada una
	de una duracion al azar entre bmin y bmax (inclusive). 
	@Parameters:
		n = params[0] => numero de llamadas bloqueantes
		bmin = params[1] => valor minimo
		bmax = params[2] => valor maximo
	@return: void
*/
void TaskConsola(int pid, vector<int> params) { // params: n (llamadas), bmin y bmax (tiempo)
	for(int i = 0; i < params[0]; i++) {
		int tiempo = rand() % (params[2] + 1 - params[1]) + params[1];
		uso_IO(pid, tiempo);
	}
}

void TaskBatch(int pid, vector<int> params) { // params: total_cpu, cant_bloqueos
	// momentos_pseudoaleatorios: 0 = se ejecuta llamada CPU, 1 = se ejecuta llamada bloqueante.
	// Inicializamos todos los momentos con 0 para que se ejecute llamada a CPU.
	vector<int> momentos_pseudoaleatorios(params[0], 0); 

	// agrego Momentos aleatorios en los que se va a ejecutar, una cantidad cant_bloqueos de veces.
	int cant_bloqueos = 0;
	while(cant_bloqueos < params[1]) {
		int i = rand() % params[0];
		if(momentos_pseudoaleatorios[i] == 0) {
			momentos_pseudoaleatorios[i] = 1;
			cant_bloqueos++;
		}
	}

	for(size_t i = 0; i < momentos_pseudoaleatorios.size(); i++) {
		if(momentos_pseudoaleatorios[i] == 0) {
			uso_CPU(pid, 1);
		} else {
			uso_IO(pid, 1);
		}
	}
}

void tasks_init(void) {
	/* Todos los tipos de tareas se deben registrar acá para poder ser usadas.
	 * El segundo parámetro indica la cantidad de parámetros que recibe la tarea
	 * como un vector de enteros, o -1 para una cantidad de parámetros variable. */
	register_task(TaskCPU, 1);
	register_task(TaskIO, 2);
	register_task(TaskAlterno, -1);
	register_task(TaskConsola, 3);
	register_task(TaskBatch, 2);
}
